package xyz.xuminghai.javafx_learn.other;

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * 2023/8/2 15:25 星期三<br/>
 * 字符画生成器
 *
 * @author xuMingHai
 */
public class CharacterPaintGeneratorApp extends Application {

    private final Pane viewPane = new Pane();

    private final BorderPane root = new BorderPane(viewPane);

    private final Button chooseImageButton = new Button("选择图片");

    private final Button generatorButton = new Button("生成字符画");
    private TextArea textArea;
    private Image image;
    private final Service<TextArea> generatorTextService = new Service<>() {

        private final char[] asciiChars = {'@', '#', '%', '$', '&', 'B', 'A', 'R', 'N', 'K', 'W', 'H', 'G', 'E', 'Q', 'P', 'X', '8', '5', '7', '0', ':', '*', '.', ' '};

        @Override
        protected Task<TextArea> createTask() {
            return new Task<>() {
                @Override
                protected TextArea call() {
                    PixelReader pixelReader = image.getPixelReader();
                    if (pixelReader == null) {
                        throw new IllegalArgumentException("图片不支持读取");
                    }
                    return generateText(pixelReader);
                }

                private TextArea generateText(PixelReader pixelReader) {
                    int imageWidth = (int) image.getWidth(), imageHeight = (int) image.getHeight();
                    StringBuilder stringBuilder = new StringBuilder((imageWidth * imageHeight) + (2 * imageHeight));
                    for (int y = 0; y < imageHeight; y++) {
                        for (int x = 0; x < imageWidth; x++) {
                            int argb = pixelReader.getArgb(x, y);
                            int red = argb >> 16 & 0XFF;
                            int green = argb >> 8 & 0XFF;
                            int blue = argb & 0XFF;
                            int gray = (int) ((0.3 * red) + (0.59 * green) + (0.11 * blue));
                            stringBuilder.append(generateChar(gray));
                        }
                        stringBuilder.append(System.lineSeparator());
                    }
                    return new TextArea(stringBuilder.toString());
                }

                private char generateChar(int gray) {
                    return asciiChars[Math.min((gray / 10), asciiChars.length - 1)];
                }

            };
        }

        @Override
        protected void succeeded() {
            textArea = getValue();
            try {
                Path path = Paths.get(System.getProperty("user.home") + File.separator, "Desktop", "character-image.txt");
                Files.writeString(path, textArea.getText());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            textArea.setFont(Font.font(1.0));
            textArea.setEditable(false);
            textArea.prefWidthProperty().bind(viewPane.widthProperty());
            textArea.prefHeightProperty().bind(viewPane.heightProperty());
            ObservableList<Node> list = viewPane.getChildren();
            list.clear();
            list.add(textArea);
            image = null;
            super.reset();
        }

        @Override
        protected void failed() {
            Alert alert = new Alert(Alert.AlertType.ERROR, super.getException().getMessage());
            alert.show();
            super.reset();
        }

    };

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void init() {
        root.setTop(new HBox(30.0, chooseImageButton, generatorButton));
        generatorButton.setOnAction(event -> {
            if (image == null) {
                Alert alert = new Alert(Alert.AlertType.INFORMATION, "请先选择图片");
                alert.show();
                return;
            }
            generatorTextService.start();
        });
    }

    private void initAction(Stage primaryStage) {
        FileChooser fileChooser = new FileChooser();
        // 初始打开目录
        fileChooser.setInitialDirectory(new File(System.getProperty("user.home") + File.separator + "Pictures"));
        fileChooser.setTitle("选择图片");
        // 文件选择过滤器
        fileChooser.getExtensionFilters().add(
                new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.jpeg")
        );
        chooseImageButton.setOnAction(event -> {
            File file = fileChooser.showOpenDialog(primaryStage);
            System.out.println("file = " + file);
            if (file != null) {
                image = new Image(file.toURI().toString());
                ObservableList<Node> list = viewPane.getChildren();
                list.clear();
                list.add(new ImageView(image));
                textArea = null;
            }
        });
    }


    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle(getClass().getSimpleName());
        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        initAction(primaryStage);
        primaryStage.show();
    }

}
